// src/utils/websocket.core.ts
export enum WsReadyState {
  CONNECTING = 0,
  OPEN = 1,
  CLOSING = 2,
  CLOSED = 3,
  ERROR = 4,
}

type WebSocketOptions = {
  reconnectLimit?: number;     // 最大重连次数
  reconnectInterval?: number;  // 重连间隔(ms)
  heartBeatInterval?: number;  // 心跳间隔(ms)
  onOpen?: () => void;
  onMessage?: (msg: string) => void;
  onClose?: () => void;
  onError?: (error: Event) => void;
};

export class WebSocketService {
  private wsUrl: string;
  private options: WebSocketOptions;
  private socket: WebSocket | null = null;
  private reconnectCount = 0;
  private heartBeatTimer: number | null = null;
  private reconnectTimer: number | null = null;
  public readyState = WsReadyState.CLOSED;

  constructor(url: string, options: WebSocketOptions = {}) {
    this.wsUrl = url;
    this.options = {
      reconnectLimit: 10,
      reconnectInterval: 3000,
      heartBeatInterval: 30000,
      ...options
    };
  }

  // 建立连接
  public connect(): void {
    if (this.socket && this.readyState === WsReadyState.OPEN) return;

    this.socket = new WebSocket(this.wsUrl);
    this.readyState = WsReadyState.CONNECTING;

    this.socket.onopen = () => {
      this.readyState = WsReadyState.OPEN;
      this.reconnectCount = 0;
      this.options.onOpen?.();
      this.startHeartBeat();
    };

    this.socket.onmessage = (event) => {
      this.options.onMessage?.(event.data);
    };

    this.socket.onclose = () => {
      this.readyState = WsReadyState.CLOSED;
      this.options.onClose?.();
      this.handleReconnect();
    };

    this.socket.onerror = (error) => {
      this.readyState = WsReadyState.ERROR;
      this.options.onError?.(error);
    };
  }

  // 发送消息
  public send(data: string | object): void {
    if (this.readyState !== WsReadyState.OPEN) {
      console.error('WebSocket not connected!');
      return;
    }

    const message = typeof data === 'string' ? data : JSON.stringify(data);
    this.socket?.send(message);
  }

  // 关闭连接
  public close(): void {
    this.clearTimers();
    this.socket?.close();
    this.readyState = WsReadyState.CLOSED;
  }

  // 断线重连处理
  private handleReconnect(): void {
    this.clearTimers();

    if (this.reconnectCount >= this.options.reconnectLimit!) {
      // console.error(`Reconnect failed after ${this.options.reconnectLimit} attempts`);
      return;
    }

    this.reconnectTimer = window.setTimeout(() => {
      this.reconnectCount++;
      console.log(`Reconnecting... (attempt ${this.reconnectCount})`);
      this.connect();
    }, this.options.reconnectInterval);
  }

  // 心跳检测
  private startHeartBeat(): void {
    this.clearHeartBeat();

    this.heartBeatTimer = window.setInterval(() => {
      if (this.readyState === WsReadyState.OPEN) {
        this.send(JSON.stringify({ msgType: 'ping' }));
      }
    }, this.options.heartBeatInterval);
  }

  // 清理定时器
  private clearTimers(): void {
    this.clearHeartBeat();
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer);
      this.reconnectTimer = null;
    }
  }

  private clearHeartBeat(): void {
    if (this.heartBeatTimer) {
      clearInterval(this.heartBeatTimer);
      this.heartBeatTimer = null;
    }
  }
}
